<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket聊天室</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.3);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(135deg, #2c3e50, #34495e);
            color: white;
            padding: 20px;
            text-align: center;
        }
        
        .header h1 {
            margin-bottom: 10px;
        }
        
        .status {
            display: inline-block;
            padding: 5px 15px;
            border-radius: 20px;
            font-size: 14px;
            margin-top: 5px;
        }
        
        .status.connected {
            background: #27ae60;
        }
        
        .status.disconnected {
            background: #e74c3c;
        }
        
        .connection-panel {
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #dee2e6;
        }
        
        .input-group {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
        }
        
        .input-group input {
            flex: 1;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
        }
        
        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s;
        }
        
        .btn-primary {
            background: #3498db;
            color: white;
        }
        
        .btn-primary:hover {
            background: #2980b9;
        }
        
        .btn-danger {
            background: #e74c3c;
            color: white;
        }
        
        .btn-danger:hover {
            background: #c0392b;
        }
        
        .btn:disabled {
            background: #bdc3c7;
            cursor: not-allowed;
        }
        
        .chat-area {
            height: 400px;
            overflow-y: auto;
            padding: 20px;
            border-bottom: 1px solid #dee2e6;
        }
        
        .message {
            margin-bottom: 15px;
            padding: 10px 15px;
            border-radius: 10px;
            max-width: 80%;
            word-wrap: break-word;
        }
        
        .message.system {
            background: #ecf0f1;
            color: #7f8c8d;
            text-align: center;
            margin: 10px auto;
            font-style: italic;
        }
        
        .message.user {
            background: #3498db;
            color: white;
            margin-left: auto;
        }
        
        .message.other {
            background: #e74c3c;
            color: white;
        }
        
        .message-info {
            font-size: 12px;
            opacity: 0.8;
            margin-bottom: 5px;
        }
        
        .input-area {
            padding: 20px;
            display: flex;
            gap: 10px;
        }
        
        .message-input {
            flex: 1;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            resize: none;
            height: 60px;
        }
        
        .send-btn {
            background: #27ae60;
            color: white;
            border: none;
            border-radius: 5px;
            padding: 0 25px;
            cursor: pointer;
            font-size: 14px;
        }
        
        .send-btn:hover:not(:disabled) {
            background: #219a52;
        }
        
        .send-btn:disabled {
            background: #bdc3c7;
            cursor: not-allowed;
        }
        
        .timestamp {
            font-size: 11px;
            opacity: 0.7;
            margin-top: 3px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>WebSocket聊天室</h1>
            <div id="status" class="status disconnected">未连接</div>
        </div>
        
        <div class="connection-panel">
            <div class="input-group">
                <input type="text" id="serverUrl" placeholder="服务器地址" value="ws://localhost:8080/socket-server/websocket">
                <input type="text" id="username" placeholder="请输入用户名" value="用户">
            </div>
            <div class="input-group">
                <button id="connectBtn" class="btn btn-primary">连接服务器</button>
                <button id="disconnectBtn" class="btn btn-danger" disabled>断开连接</button>
            </div>
        </div>
        
        <div id="chatArea" class="chat-area"></div>
        
        <div class="input-area">
            <textarea id="messageInput" class="message-input" placeholder="输入消息..." disabled></textarea>
            <button id="sendBtn" class="send-btn" disabled>发送</button>
        </div>
    </div>

    <script>
        class WebSocketClient {
            constructor() {
                this.socket = null;
                this.isConnected = false;
                this.initializeElements();
                this.bindEvents();
            }
            
            initializeElements() {
                this.statusElement = document.getElementById('status');
                this.chatArea = document.getElementById('chatArea');
                this.messageInput = document.getElementById('messageInput');
                this.sendBtn = document.getElementById('sendBtn');
                this.connectBtn = document.getElementById('connectBtn');
                this.disconnectBtn = document.getElementById('disconnectBtn');
                this.serverUrlInput = document.getElementById('serverUrl');
                this.usernameInput = document.getElementById('username');
            }
            
            bindEvents() {
                this.connectBtn.addEventListener('click', () => this.connect());
                this.disconnectBtn.addEventListener('click', () => this.disconnect());
                this.sendBtn.addEventListener('click', () => this.sendMessage());
                this.messageInput.addEventListener('keypress', (e) => {
                    if (e.key === 'Enter' && !e.shiftKey) {
                        e.preventDefault();
                        this.sendMessage();
                    }
                });
            }
            
            connect() {
                const serverUrl = this.serverUrlInput.value;
                const username = this.usernameInput.value || '匿名用户';
                
                if (!serverUrl) {
                    this.showSystemMessage('请输入服务器地址');
                    return;
                }
                
                try {
                    this.socket = new WebSocket(serverUrl);
                    this.socket.onopen = () => this.onOpen(username);
                    this.socket.onmessage = (event) => this.onMessage(event);
                    this.socket.onclose = () => this.onClose();
                    this.socket.onerror = (error) => this.onError(error);
                } catch (error) {
                    this.showSystemMessage('连接失败: ' + error.message);
                }
            }
            
            onOpen(username) {
                this.isConnected = true;
                this.updateConnectionStatus();
                this.showSystemMessage('连接服务器成功！');
                
                // 发送用户加入消息
                const joinMessage = {
                    type: 'JOIN',
                    sender: username,
                    content: `${username} 加入了聊天室`,
                    timestamp: Date.now()
                };
                
                this.socket.send(JSON.stringify(joinMessage));
            }
            
            onMessage(event) {
                try {
                    const message = JSON.parse(event.data);
                    this.displayMessage(message);
                } catch (error) {
                    // 处理普通文本消息
                    this.displayMessage({
                        type: 'TEXT',
                        content: event.data,
                        sender: '其他用户',
                        timestamp: Date.now()
                    });
                }
            }
            
            onClose() {
                this.isConnected = false;
                this.updateConnectionStatus();
                this.showSystemMessage('连接已断开');
            }
            
            onError(error) {
                this.showSystemMessage('连接错误: ' + error);
            }
            
            disconnect() {
                if (this.socket) {
                    this.socket.close();
                    this.socket = null;
                }
                this.isConnected = false;
                this.updateConnectionStatus();
            }
            
            sendMessage() {
                if (!this.isConnected || !this.socket) {
                    this.showSystemMessage('未连接到服务器');
                    return;
                }
                
                const content = this.messageInput.value.trim();
                const username = this.usernameInput.value || '匿名用户';
                
                if (!content) {
                    return;
                }
                
                const message = {
                    type: 'TEXT',
                    sender: username,
                    content: content,
                    timestamp: Date.now()
                };
                
                try {
                    this.socket.send(JSON.stringify(message));
                    this.messageInput.value = '';
                    
                    // 显示自己发送的消息
                    this.displayMessage({
                        ...message,
                        isOwn: true
                    });
                    
                } catch (error) {
                    this.showSystemMessage('发送消息失败: ' + error.message);
                }
            }
            
            displayMessage(message) {
                const messageElement = document.createElement('div');
                
                if (message.type === 'SYSTEM') {
                    messageElement.className = 'message system';
                    messageElement.innerHTML = `
                        <div class="message-content">${message.content}</div>
                        <div class="timestamp">${this.formatTime(message.timestamp)}</div>
                    `;
                } else {
                    const isOwn = message.isOwn || message.sender === (this.usernameInput.value || '匿名用户');
                    messageElement.className = `message ${isOwn ? 'user' : 'other'}`;
                    messageElement.innerHTML = `
                        <div class="message-info">${isOwn ? '我' : message.sender}</div>
                        <div class="message-content">${this.escapeHtml(message.content)}</div>
                        <div class="timestamp">${this.formatTime(message.timestamp)}</div>
                    `;
                }
                
                this.chatArea.appendChild(messageElement);
                this.chatArea.scrollTop = this.chatArea.scrollHeight;
            }
            
            showSystemMessage(content) {
                this.displayMessage({
                    type: 'SYSTEM',
                    content: content,
                    timestamp: Date.now()
                });
            }
            
            updateConnectionStatus() {
                if (this.isConnected) {
                    this.statusElement.textContent = '已连接';
                    this.statusElement.className = 'status connected';
                    this.connectBtn.disabled = true;
                    this.disconnectBtn.disabled = false;
                    this.messageInput.disabled = false;
                    this.sendBtn.disabled = false;
                    this.serverUrlInput.disabled = true;
                    this.usernameInput.disabled = true;
                } else {
                    this.statusElement.textContent = '未连接';
                    this.statusElement.className = 'status disconnected';
                    this.connectBtn.disabled = false;
                    this.disconnectBtn.disabled = true;
                    this.messageInput.disabled = true;
                    this.sendBtn.disabled = true;
                    this.serverUrlInput.disabled = false;
                    this.usernameInput.disabled = false;
                }
            }
            
            formatTime(timestamp) {
                return new Date(timestamp).toLocaleTimeString('zh-CN');
            }
            
            escapeHtml(unsafe) {
                return unsafe
                    .replace(/&/g, "&amp;")
                    .replace(/</g, "&lt;")
                    .replace(/>/g, "&gt;")
                    .replace(/"/g, "&quot;")
                    .replace(/'/g, "&#039;");
            }
        }
        
        // 初始化客户端
        document.addEventListener('DOMContentLoaded', () => {
            new WebSocketClient();
        });
    </script>
</body>
</html>